/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.programacao.concorrente.problema;

import br.com.programacao.concorrente.auxiliar.Constantes;
import br.com.programacao.concorrente.auxiliar.Log;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.Calendar;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Afonso
 */
public class Produtor implements Runnable {

    private final Buffer buffer;
    private final int execution;

    public Produtor(Buffer buffer, int execution) {
        this.buffer = buffer;
        this.execution = execution;
    }

    @Override
    public void run() {
        long timeInitThread = Constantes.getTimeMillis();
        int qtdTheads = 0;
        final String inicioThread = "Inicio da thread consumidora" + " " + Thread.currentThread().getName() + " "
                + " Execução:" + this.execution + " "
                + Calendar.getInstance().getTime();

        //Grava no log o inicio
        Log.getLogger(this.getClass()).info(inicioThread);
        while ((Constantes.getTimeMillis() - Constantes.INSTANT_INIT) < Constantes.TIME_EXECUTION) {

            if (!buffer.isFull()) {
                try {
                    long inicio = Constantes.getTimeMillis();
                    Date dtInicio = Calendar.getInstance().getTime();
                    File file = generateFile();
                    String id = gravaLogInicio(file, dtInicio);
                    Thread.sleep(Constantes.INTERVAL_THREAD_PRODUCT);
                    Thread.sleep(Constantes.INTERVAL_THREAD);
                    gravaLogFim(id, file, inicio);

                } catch (Exception ex) {
                    Logger.getLogger(Produtor.class.getName()).log(Level.SEVERE, null, ex);
                }
            } else {
                try {
                    //intervalo para aguardar espaco no buffer
                    wait();
                } catch (InterruptedException ex) {
                    Logger.getLogger(Produtor.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        long timeEndThread = Constantes.getTimeMillis();
        final String terminoThread = "Termino da thread" + " " + Thread.currentThread().getName()
                + " Execução:" + this.execution + " "
                + " " + Calendar.getInstance().getTime();
        Log.getLogger(this.getClass()).info(terminoThread);
        Log.includeLogFileExecution(this.execution, (timeEndThread - timeInitThread), qtdTheads);
    }

   /**
    *  Gera um arquivo para buffer e incrementa o numero de arquivos criados
    * @return Arquivo criado
    * @throws FileNotFoundException
    * @throws UnsupportedEncodingException
    * @throws Exception 
    */
    private File generateFile() throws FileNotFoundException, UnsupportedEncodingException, Exception {
        Constantes.LAST_NAME_FILE_GENERATE++;
        File file = new File(String.format("%04d", Constantes.LAST_NAME_FILE_GENERATE) + ".file");
        try (PrintWriter writer = new PrintWriter(file, "UTF-8")) {
            for (int j = 0; j < Constantes.QTD_CARACTERES_FILE; j++) {
                writer.println('W');
            }
        }
        this.buffer.setFile(file);
        Constantes.QTD_CREATED++;
        file.delete();
        return file;
    }

    /**
     * Grava no log o fim do processamento do arquivo
     *
     * @param file
     * @param dtInicio
     * @return id do pedido
     * @throws NullPointerException
     */
    private String gravaLogInicio(File file, Date dtInicio) throws NullPointerException {
        String id = String.valueOf(Thread.currentThread().getName());
        String inicioLog = "Thread Produtora #" + id + " Pedido #" + file.getName() + " Inicio:" + dtInicio;
        Log.getLogger(this.getClass()).debug(inicioLog);
        return id;
    }

    /**
     * Grava no log o fim do processamento do arquivo
     *
     * @param id
     * @param file
     * @param inicio
     * @throws NullPointerException
     */
    private void gravaLogFim(String id, File file, long inicio) throws NullPointerException {
        String fimLog = "Thread Produtora #" + id + " Pedido #" + file.getName() + " Termino:" + Calendar.getInstance().getTime();
        Log.getLogger(this.getClass()).debug(fimLog);
        long fim = Constantes.getTimeMillis();
        Log.includeLogFileThread(this.execution, id, file.getName(), (fim - inicio), "Produtora");
    }

}
